<template>
  <div class="attachment-list">
    <div class="attachment-header">
      <el-button 
        v-if="!readonly" 
        type="primary" 
        size="small"
        plain
        @click="handleAddAttachment"
      >
        上传附件
      </el-button>
    </div>
    
    <div v-if="loading" class="attachment-loading">
      <el-skeleton :rows="3" animated />
    </div>
    
    <div v-else-if="attachments.length === 0" class="attachment-empty">
      <el-empty description="暂无附件" />
    </div>
    
    <el-table
      v-else
      :data="attachments"
      style="width: 100%"
      size="small"
    >
      <el-table-column prop="filename" label="附件名称" min-width="180" show-overflow-tooltip />
      <el-table-column prop="filesize" label="文件大小" width="120">
        <template #default="scope">
          {{ formatFileSize(scope.row.filesize) }}
        </template>
      </el-table-column>
      <el-table-column prop="description" label="描述" min-width="150" show-overflow-tooltip />
      <el-table-column prop="upload_time" label="上传时间" width="180">
        <template #default="scope">
          {{ formatDateTime(scope.row.upload_time) }}
        </template>
      </el-table-column>
      <el-table-column prop="uploader" label="上传人" width="120" show-overflow-tooltip />
      <el-table-column label="操作" width="240" fixed="right">
        <template #default="scope">
          <el-button size="small" type="primary" @click="handlePreview(scope.row)" :disabled="false">预览</el-button>
          <el-button size="small" type="success" @click="handleDownload(scope.row.id)" :disabled="false">下载</el-button>
          <el-button 
            v-if="!readonly" 
            size="small" 
            type="danger" 
            @click="handleDelete(scope.row.id)"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <!-- 预览对话框 -->
    <el-dialog
      v-model="previewVisible"
      :title="previewFile.filename"
      width="80%"
      top="5vh"
      destroy-on-close
      fullscreen
    >
      <div class="preview-container">
        <div v-if="previewLoading" class="preview-loading">
          <el-skeleton :rows="10" animated />
        </div>
        <div v-else>
          <!-- 图片预览 -->
          <div v-if="isImage" class="image-preview">
            <img :src="previewUrl" alt="预览图片" />
          </div>
          
          <!-- PDF预览 -->
          <div v-else-if="isPdf" class="pdf-preview">
            <iframe :src="previewUrl" width="100%" height="600"></iframe>
          </div>
          
          <!-- 文本预览 -->
          <div v-else-if="isText" class="text-preview">
            <pre>{{ previewContent }}</pre>
          </div>
          
          <!-- 其他文件类型 -->
          <div v-else class="unsupported-preview">
            <el-empty description="该文件类型暂不支持预览，请下载后查看">
              <template #extra>
                <el-button type="primary" @click="handleDownload(previewFile.id)">下载文件</el-button>
              </template>
            </el-empty>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { ref, computed, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import attachmentApi from '@/api/attachmentApi'

export default {
  name: 'AttachmentList',
  props: {
    attachments: {
      type: Array,
      default: () => []
    },
    module: {
      type: String,
      required: true
    },
    moduleId: {
      type: [String, Number],
      required: true
    },
    readonly: {
      type: Boolean,
      default: false
    }
  },
  emits: ['refresh', 'add-attachment'],
  setup(props, { emit }) {
    const loading = ref(false)
    // 预览相关状态
    const previewVisible = ref(false)
    const previewLoading = ref(false)
    const previewFile = ref({})
    const previewUrl = ref('')
    const previewContent = ref('')
    
    // 判断文件类型
    const isImage = computed(() => {
      const imageTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml']
      return imageTypes.includes(previewFile.value.filetype)
    })
    
    const isPdf = computed(() => {
      return previewFile.value.filetype === 'application/pdf'
    })
    
    const isText = computed(() => {
      const textTypes = [
        'text/plain', 'text/html', 'text/css', 'text/javascript',
        'application/json', 'application/xml'
      ]
      return textTypes.includes(previewFile.value.filetype) || previewFile.value.filename?.endsWith('.txt')
    })
    
    // 格式化文件大小
    const formatFileSize = (bytes) => {
      if (!bytes || bytes === 0) return '0 B'
      
      const units = ['B', 'KB', 'MB', 'GB', 'TB']
      const i = Math.floor(Math.log(bytes) / Math.log(1024))
      return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + units[i]
    }
    
    // 格式化日期时间
    const formatDateTime = (dateString) => {
      if (!dateString) return ''
      
      const date = new Date(dateString)
      const year = date.getFullYear()
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      const hours = String(date.getHours()).padStart(2, '0')
      const minutes = String(date.getMinutes()).padStart(2, '0')
      
      return `${year}-${month}-${day} ${hours}:${minutes}`
    }
    
    const loadAttachments = async () => {
      if (!props.moduleId) return
      loading.value = true
      try {
        await attachmentApi.list(props.module, props.moduleId)
      } finally {
        loading.value = false
      }
    }
    
    // 处理预览
    const handlePreview = async (file) => {
      previewFile.value = file
      previewVisible.value = true
      previewLoading.value = true
      
      try {
        const url = attachmentApi.preview(file.id)
          if (isImage.value || isPdf.value) {
          previewUrl.value = url
          } else if (isText.value) {
          const response = await fetch(url)
            previewContent.value = await response.text()
        } else {
          previewUrl.value = url
        }
      } catch (error) {
        ElMessage.error('预览文件失败')
      } finally {
        previewLoading.value = false
      }
    }
    
    // 处理下载
    const handleDownload = async (attachmentId) => {
      try {
        // 找到当前附件对象
        const fileObj = props.attachments.find(item => item.id === attachmentId)
        const res = await attachmentApi.download(attachmentId)
        const blob = new Blob([res.data])
        const url = window.URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = url
        // 优先从响应头获取文件名
        let filename = fileObj?.filename || 'attachment'
        const disposition = res.headers && (res.headers['content-disposition'] || res.headers['Content-Disposition'])
        if (disposition) {
          // 兼容 filename*=utf-8'' 及 filename="xxx"
          let match = disposition.match(/filename\*=UTF-8''([^;\n]*)/i)
          if (match && match[1]) {
            filename = decodeURIComponent(match[1])
          } else {
            match = disposition.match(/filename="?([^";\n]*)"?/i)
            if (match && match[1]) {
              filename = decodeURIComponent(match[1])
            }
          }
        }
        link.download = filename
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        window.URL.revokeObjectURL(url)
      } catch (error) {
        ElMessage.error('下载文件失败')
      }
    }
    
    // 处理删除
    const handleDelete = async (attachmentId) => {
      ElMessageBox.confirm('确定要删除此附件吗？删除后无法恢复。', '警告', {
        confirmButtonText: '删除',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          return attachmentApi.delete(props.module, props.moduleId, attachmentId)
        })
        .then(() => {
          ElMessage.success('删除成功')
          loadAttachments()
          emit('refresh')
        })
        .catch(error => {
          if (error !== 'cancel' && error !== 'close') {
            ElMessage.error('删除附件失败')
            console.error(error)
          }
        })
    }
    
    // 添加附件
    const handleAddAttachment = () => {
      emit('add-attachment')
    }
    
    watch(() => props.moduleId, loadAttachments, { immediate: true })
    
    return {
      loading,
      formatFileSize,
      formatDateTime,
      handleDownload,
      handleDelete,
      handleAddAttachment,
      handlePreview,
      previewVisible,
      previewLoading,
      previewFile,
      previewUrl,
      previewContent,
      isImage,
      isPdf,
      isText
    }
  }
}
</script>

<style scoped>
.attachment-list {
  width: 100%;
}

.attachment-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.attachment-loading {
  padding: 20px 0;
}

.attachment-empty {
  padding: 10px 0 5px 0;
  text-align: center;
}

.attachment-empty :deep(.el-empty) {
  padding: 0 !important;
}

.attachment-empty :deep(.el-empty__image) {
  width: 40px;
  height: 40px;
  margin-bottom: 2px;
}

.attachment-empty :deep(.el-empty__description) {
  font-size: 13px;
  margin-top: 2px;
}

:deep(.el-button--small) {
  padding: 6px 10px;
  font-size: 13px;
  margin: 0 2px;
}

:deep(.el-table) {
  font-size: 14px;
}

:deep(.el-table th) {
  font-size: 14px;
  font-weight: 500;
}

:deep(.el-table td) {
  font-size: 14px;
}

/* 预览相关样式 */
.preview-container {
  width: 100%;
  min-height: 400px;
}

.preview-loading {
  padding: 20px;
}

.image-preview {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 20px;
}

.image-preview img {
  max-width: 100%;
  max-height: 80vh;
  object-fit: contain;
}

.pdf-preview {
  width: 100%;
  height: 80vh;
}

.text-preview {
  padding: 20px;
  background-color: #f5f7fa;
  border-radius: 4px;
  overflow: auto;
  max-height: 80vh;
}

.text-preview pre {
  white-space: pre-wrap;
  word-wrap: break-word;
  font-family: 'Courier New', Courier, monospace;
  margin: 0;
}

.unsupported-preview {
  padding: 40px;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 300px;
}

/* 响应式调整 */
@media screen and (max-width: 768px) {
  .attachment-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
}
</style> 